
package com.eworking.eim.message;

import java.util.ArrayList;
import java.util.List;

import com.eworking.eim.EIMSessionManager;
import com.eworking.eim.database.EIMDatabaseManager;
import com.eworking.eim.database.EIMDatabaseTable;
import com.eworking.eim.util.EIMLog;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class EIMMessageTable implements EIMDatabaseTable {
    
    /** 日志输出标记 */
    private static final String _TAG = EIMMessageTable.class.getSimpleName();
    
    /** 表名 */
    private static final String _TABLE_NAME = "IM_MESSAGE";
    
    /** 数据库管理 */
    private EIMDatabaseManager databaseManager = null;
    
    private static EIMMessageTable messageTable = null;
    
    public static EIMMessageTable getInstance() {
        return messageTable;
    }
    
    public EIMMessageTable(EIMDatabaseManager databaseManager) {
        this.databaseManager = databaseManager;
        messageTable = this;
    }
    
    /**
     * 将消息保存到数据库中
     * 
     * @param message 消息实体
     */
    public void insertMessage(EIMMessage message) {
        try {
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put(Fields._MSG_ID, message.getMsgId());
            values.put(Fields._MSG_TIME, message.getMsgTime());
            values.put(Fields._MSG_TYPE, message.direct.ordinal());
            values.put(Fields._MSG_ISACKED, message.isAcked());
            values.put(Fields._MSG_STATUS, message.status.ordinal());
            String currentAccount = EIMSessionManager.getInstance(null).getCurrentUser().getAccount();
            // 设置聊天室参与者
            String participant = "";
            if (message.getFrom().equals(currentAccount)) {
                participant = message.getTo();
            } else {
                participant = message.getFrom();
            }
            values.put(Fields._MSG_PARTICIPANT, participant);
            // 消息内容
            values.put(Fields._MSG_BODY, EIMMessageEncoder.convertMsgToJSON(message, true));
            // 是否为群组消息
            if (message.chatType == EIMMessage.ChatType.GroupChat) {
                values.put(Fields._MSG_GROUP, message.getTo());
            } else {
                values.putNull(Fields._MSG_GROUP);
            }
            // 插入数据库中
            database.insert(_TABLE_NAME, null, values);
        } catch (Exception e) {
            EIMLog.e(_TAG, "将消息插入数据库失败：消息内容" + message.toString() + "   错误信息：" + e.getMessage());
        }
    }
    
    /**
     * 根据消息ID删除消息
     * 
     * @param msgId 消息ID
     */
    public void deleteMessage(String msgId) {
        try {
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            database.delete(_TABLE_NAME, Fields._MSG_ID + " = ? ", new String[] { msgId });
        } catch (Exception e) {
            EIMLog.e(_TAG, "根据消息ID：" + msgId + "删除消息失败，" + e.getMessage());
        }
    }
    
    /**
     * 根据消息获取所有的参与人
     * 
     * @return
     */
    public List<String> queryAllParticipantsFromMsg() {
        List<String> lstAllParts = new ArrayList<String>();
        try {
            String sql =
                "SELECT DISTINCT " + Fields._MSG_PARTICIPANT + " FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_GROUP
                    + " IS NULL";
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            Cursor cursor = database.rawQuery(sql, null);
            if (!(cursor.moveToFirst())) {
                cursor.close();
                return lstAllParts;
            }
            do {
                lstAllParts.add(cursor.getString(0));
            } while (cursor.moveToNext());
            cursor.close();
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取所有单聊消息的参与人失败：" + e.getMessage());
        }
        return lstAllParts;
    }
    
    /**
     * 获取所有消息涉及的群组
     * 
     * @return
     */
    public List<String> queryAllGroupsFromMsg() {
        List<String> lstAllGroups = new ArrayList<String>();
        try {
            String sql =
                "SELECT DISTINCT " + Fields._MSG_GROUP + " FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_GROUP
                    + " IS NOT NULL";
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            Cursor cursor = database.rawQuery(sql, null);
            if (!(cursor.moveToFirst())) {
                cursor.close();
                return lstAllGroups;
            }
            do {
                lstAllGroups.add(cursor.getString(0));
            } while (cursor.moveToNext());
            cursor.close();
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取所有单聊消息的参与人失败：" + e.getMessage());
        }
        return lstAllGroups;
    }
    
    /**
     * 获取群组ID获取群组消息
     * 
     * @param groupName
     * @return
     */
    public List<EIMMessage> queryGroupMessages(String groupName) {
        List<EIMMessage> lstGroupMessages = new ArrayList<EIMMessage>();
        try {
            String sql =
                "SELECT * FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_GROUP + " = " + groupName + " ORDER BY "
                    + Fields._MSG_TIME;
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            Cursor cursor = database.rawQuery(sql, new String[] { groupName });
            if (!(cursor.moveToFirst())) {
                cursor.close();
                return lstGroupMessages;
            }
            do {
                EIMMessage message = loadMsgFromCursor(cursor);
                lstGroupMessages.add(message);
            } while (cursor.moveToNext());
            cursor.close();
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取群组消息失败，群组ID：" + groupName + "  错误信息：" + e.getMessage());
        }
        return lstGroupMessages;
    }
    
    /**
     * 根据群组ID获取群组所有消息 ，上下滑动加载数据
     * 
     * @param groupName 群组ID
     * @param msgId 消息ID
     * @param limit 每页加载数量
     * @return
     */
    public List<EIMMessage> queryGroupMessages(String groupName, String msgId, int limit) {
        List<EIMMessage> lstGroupMessages = new ArrayList<EIMMessage>();
        try {
            
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            Cursor cursor = null;
            if (msgId != null) {
                String sql = "SELECT _ID FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_ID + " = ? ";
                cursor = database.rawQuery(sql, new String[] { msgId });
                if ((cursor != null) && (cursor.moveToFirst())) {
                    int _id = cursor.getInt(cursor.getColumnIndex("_ID"));
                    String sqlGroup =
                        "SELECT * FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_GROUP
                            + " = ? AND _ID < ? ORDER BY _ID LIMIT ?";
                    cursor =
                        database.rawQuery(sqlGroup,
                            new String[] { groupName, String.valueOf(_id), String.valueOf(limit) });
                }
            } else {
                String sql = "SELECT * FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_GROUP + " = ? LIMIT ?";
                cursor = database.rawQuery(sql, new String[] { groupName, String.valueOf(limit) });
            }
            if (!(cursor.moveToFirst())) {
                cursor.close();
                return lstGroupMessages;
            }
            do {
                EIMMessage message = loadMsgFromCursor(cursor);
                lstGroupMessages.add(message);
            } while (cursor.moveToNext());
            cursor.close();
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取群组消息失败，群组ID：" + groupName + "  错误信息：" + e.getMessage());
        }
        return lstGroupMessages;
    }
    
    /**
     * 获取与参与者的聊天记录
     * 
     * @param participant 参与者
     * @return
     */
    public List<EIMMessage> queryMessages(String participant) {
        List<EIMMessage> lstMessages = new ArrayList<EIMMessage>();
        try {
            String sql =
                "SELECT * FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_PARTICIPANT + " = ? AND " + Fields._MSG_GROUP
                    + " IS NULL ORDER BY " + Fields._MSG_TIME;
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            Cursor cursor = database.rawQuery(sql, new String[] { participant });
            if (!(cursor.moveToFirst())) {
                cursor.close();
                return lstMessages;
            }
            do {
                EIMMessage message = loadMsgFromCursor(cursor);
                lstMessages.add(message);
            } while (cursor.moveToNext());
            cursor.close();
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取与参与者的消息记录失败，参与者：" + participant + "  错误信息：" + e.getMessage());
        }
        return lstMessages;
    }
    
    /**
     * 根据与参与人的消息记录 ，上下滑动加载数据
     * 
     * @param participant 参与人
     * @param msgId 消息ID
     * @param limit 每页加载数量
     * @return
     */
    public List<EIMMessage> queryMessages(String participant, String msgId, int limit) {
        List<EIMMessage> lstMessages = new ArrayList<EIMMessage>();
        try {
            
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            Cursor cursor = null;
            if (msgId != null) {
                String sql = "SELECT _ID FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_ID + " = ? ";
                cursor = database.rawQuery(sql, new String[] { msgId });
                if ((cursor != null) && (cursor.moveToFirst())) {
                    int _id = cursor.getInt(cursor.getColumnIndex("_ID"));
                    String sqlGroup =
                        "SELECT * FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_PARTICIPANT + " = ? AND _ID < ? AND "
                            + Fields._MSG_GROUP + " IS NULL ORDER BY _ID LIMIT ?";
                    cursor =
                        database.rawQuery(sqlGroup,
                            new String[] { participant, String.valueOf(_id), String.valueOf(limit) });
                }
            } else {
                String sql =
                    "SELECT * FROM " + _TABLE_NAME + " WHERE " + Fields._MSG_PARTICIPANT + " = ? AND "
                        + Fields._MSG_GROUP + " IS NULL LIMIT ?";
                cursor = database.rawQuery(sql, new String[] { participant, String.valueOf(limit) });
            }
            if (!(cursor.moveToFirst())) {
                cursor.close();
                return lstMessages;
            }
            do {
                EIMMessage message = loadMsgFromCursor(cursor);
                lstMessages.add(message);
            } while (cursor.moveToNext());
            cursor.close();
        } catch (Exception e) {
            EIMLog.e(_TAG, "获取与参与人的消息记录，参与人：" + participant + "  错误信息：" + e.getMessage());
        }
        return lstMessages;
    }
    
    /**
     * 删除与参与者的会话消息
     * 
     * @param participant 参与人
     */
    public void deleteConversions(String participant) {
        try {
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            database.delete(_TABLE_NAME, Fields._MSG_PARTICIPANT + " = ? ", new String[] { participant });
        } catch (Exception e) {
            EIMLog.e(_TAG, "根据参与人：" + participant + "删除消息失败，" + e.getMessage());
        }
    }
    
    /**
     * 更新消息的确认状态
     * 
     * @param msgId 消息ID
     * @param isAcked 是否确认
     */
    public void updateMessageAck(String msgId, boolean isAcked) {
        try {
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            ContentValues values = new ContentValues();
            values.put(Fields._MSG_ISACKED, isAcked);
            database.update(_TABLE_NAME, values, Fields._MSG_ID + " = ?", new String[] { msgId });
        } catch (Exception e) {
            EIMLog.e(_TAG, "根据消息ID：" + msgId + "更新消息的确认状态失败：" + e.getMessage());
        }
    }
    
    /**
     * 更新消息信息
     * 
     * @param msgId 消息ID
     * @param values 消息数据
     */
    public void updateMessage(String msgId, ContentValues values) {
        try {
            SQLiteDatabase database = this.databaseManager.getWritableDatabase();
            database.update(_TABLE_NAME, values, Fields._MSG_ID + " = ?", new String[] { msgId });
        } catch (Exception e) {
            EIMLog.e(_TAG, "根据消息ID：" + msgId + "更新消息信息失败：" + e.getMessage());
        }
    }
    
    /**
     * 转换消息
     * 
     * @param cursor
     * @return
     */
    private EIMMessage loadMsgFromCursor(Cursor cursor) {
        // 消息内容
        String msgBody = cursor.getString(cursor.getColumnIndex(Fields._MSG_BODY));
        EIMMessage message = EIMMessageEncoder.convertJSONToMessage(msgBody);
        
        message.msgId = cursor.getString(cursor.getColumnIndex(Fields._MSG_ID));
        message.msgTime = cursor.getLong(cursor.getColumnIndex(Fields._MSG_TIME));
        // 消息类型 --发送 or 接收
        int type = cursor.getInt(cursor.getColumnIndex(Fields._MSG_TYPE));
        if (type == EIMMessage.Direct.SEND.ordinal()) {
            message.direct = EIMMessage.Direct.SEND;
        } else {
            message.direct = EIMMessage.Direct.RECEIVE;
        }
        // 消息状态
        int status = cursor.getInt(cursor.getColumnIndex(Fields._MSG_STATUS));
        if (status == EIMMessage.Status.CREATE.ordinal()) {
            message.status = EIMMessage.Status.CREATE;
        } else if (status == EIMMessage.Status.INPROGRESS.ordinal()) {
            message.status = EIMMessage.Status.INPROGRESS;
        } else if (status == EIMMessage.Status.SUCCESS.ordinal()) {
            message.status = EIMMessage.Status.SUCCESS;
        } else if (status == EIMMessage.Status.FAIL.ordinal()) {
            message.status = EIMMessage.Status.FAIL;
        }
        // 是否确认
        int isAcked = cursor.getInt(cursor.getColumnIndex(Fields._MSG_ISACKED));
        if (isAcked == 0) {
            message.isAcked = false;
        } else {
            message.isAcked = true;
        }
        // 是否读取
        message.unread = false;
        // 群组ID
        String groupname = cursor.getString(cursor.getColumnIndex(Fields._MSG_GROUP));
        if (groupname == null) {
            message.setChatType(EIMMessage.ChatType.Chat);
        } else {
            message.setChatType(EIMMessage.ChatType.GroupChat);
            message.setTo(groupname);
        }
        return message;
    }
    
    @Override
    public void onCreated(SQLiteDatabase database) {
        // 创建表语句
        String sql =
            "CREATE TABLE " + _TABLE_NAME + " ( " + Fields._ID + " INTEGER PRIMARY KEY AUTOINCREMENT , "
                + Fields._MSG_ID + " TEXT ," + Fields._MSG_TIME + " INTEGER ," + Fields._MSG_TYPE + " INTEGER ,"
                + Fields._MSG_ISACKED + " INTEGER," + Fields._MSG_STATUS + " INTEGER," + Fields._MSG_PARTICIPANT
                + " TEXT NOT NULL," + Fields._MSG_BODY + " TEXT NOT NULL," + Fields._MSG_GROUP + " TEXT);";
        database.execSQL(sql);
    }
    
    @Override
    public void onDroped(SQLiteDatabase database) {
        // 删除表语句
        String sql = "DROP TABLE IF EXISTS " + _TABLE_NAME;
        database.execSQL(sql);
    }
    
    public static final class Fields {
        
        /** 消息主键 */
        public static final String _ID = "_id";
        
        /** 消息ID */
        public static final String _MSG_ID = "msg_id";
        
        /** 消息时间 */
        public static final String _MSG_TIME = "msg_time";
        
        /** 消息类型 发送/接收 */
        public static final String _MSG_TYPE = "msg_type";
        
        /** 消息参与者 */
        public static final String _MSG_PARTICIPANT = "msg_participant";
        
        /** 消息内容 */
        public static final String _MSG_BODY = "msg_body";
        
        /** 群组 */
        public static final String _MSG_GROUP = "msg_group";
        
        /** 是否收到 */
        public static final String _MSG_ISACKED = "msg_isacked";
        
        /** 消息状态 */
        public static final String _MSG_STATUS = "msg_status";
    }
}
